// 实现这个项目的构建任务
const { src, dest, parallel, series, watch } = require("gulp")
//删除文件
const del = require('del')
//stylelint
const stylelint = require('stylelint');
const scss = require('postcss-scss');

//将process.args转换成对象
const minimist = require('minimist');
const args = minimist(process.argv.slice(2));

//插件加载
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()

//浏览器热更新
const browserSync = require('browser-sync')
const bs = browserSync.create()

//当前执行项目的目录
const cwd = process.cwd()

//读取配置文件
let config = require("../gulp.config.js");
try {
    const loadConfig = require(`${cwd}/gulp.config.js`);
    config = Object.assign({}, config, loadConfig)
} catch (e) { }

const { data } = config;
const { src: base, dist, temp, public: publicPath, paths } = config.path || {};

//style scss文件需要预编译，然后输出到temp文件
const styles = () => {
    return src(paths.styles, { base, cwd: base })
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        .pipe(dest(temp))
        .pipe(bs.reload({ stream: true }));
}

//stylelint
const stylesLint = () => {
    return src(paths.styles, { base, cwd: base })
        .pipe(plugins.postcss([
            stylelint({ fix: args.fix })
        ], { syntax: scss }));
}

//js文件需要经过preset解析es6语法，然后输出到temp文件
const scripts = () => {
    return src(paths.scripts, { base: base, cwd: base })
        .pipe(plugins.babel({ presets: [require('@babel/preset-env')] }))
        .pipe(dest(temp))
        .pipe(bs.reload({ stream: true }));
}

//eslint
// const scriptsLint = () => {
//     return src(paths.scripts, { base, cwd: base })
//         .pipe(plugins.eslint({ fix: args.fix }))
//         .pipe(plugins.eslint.format())
//         .pipe(plugins.eslint.failAfterError());
// }


//html文件需要模板编译，然后输出到temp
const pages = () => {
    return src(paths.pages, { base: base, cwd: base })
        // 防止模板缓存导致页面不能及时更新
        .pipe(plugins.swig({ data, defaults: { cache: false } }))
        .pipe(dest(temp))
        .pipe(bs.reload({ stream: true }));
}

const image = () => {
    return src(paths.images, { base: base, cwd: base })
        .pipe(plugins.imagemin())
        .pipe(dest(dist))
}

//images需要压缩
const font = () => {
    return src('src/assets/fonts/**', { base: base, cwd: base })
        .pipe(plugins.imagemin())
        .pipe(dest(dist))
}

const extra = () => {
    return src('**', { base: publicPath, cwd: publicPath })
        .pipe(dest(dist))
}

//压缩html里面第三方包的内容，包括js,css,html
const useref = () => {
    return src(paths.pages, { base: temp, cwd: temp })
        .pipe(plugins.useref({ searchPath: [temp, '.'] }))
        // html js css
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({
            collapseWhitespace: true,
            minifyCSS: true,
            minifyJS: true
        })))
        .pipe(dest(dist))
}

const serve = () => {
    watch(paths.styles, { cwd: base }, styles)
    watch(paths.scripts, { cwd: base }, scripts)
    watch(paths.pages, { cwd: base }, pages)

    watch([
        paths.images,
        paths.fonts
    ], { cwd: base }, bs.reload)

    watch('**', { cwd: publicPath }, bs.reload)

    bs.init({
        port: 3080,
        server: {
            baseDir: [temp, dist, publicPath],
            routes: {
                '/node_modules': 'node_modules'
            }
        }
    })
}

const clean = () => {
    return del([dist, temp])
}

const lint = parallel(stylesLint);

const compile = parallel(styles, scripts, pages)

// 上线之前执行的任务
const build = series(
    clean,
    parallel(
        series(compile, useref),
        image,
        font,
        extra
    )
)

const develop = series(compile, serve)

module.exports = {
    clean,
    lint,
    build,
    develop
}
